using Godot;
using System;
using System.Collections;
using System.Collections.Generic;
using UniCoroutine;
public struct DirectAndAngle
{
    public float Angle { get; set; }
    public Vector2 Direct { get; set; }
}

public partial class MultiBulletMaker : Node2D
{
    #region props
    public float CD { get; set; } = 0.05f;
    public int MultiCount { get => _multiCount; set { SetMultiCount(value); } }
    private int _multiCount = 1;

    // 分叉火力的角度范围
    public float SpreadRangeAngle { get => _spreadRangeAngle; set { SetSpreadRangeAngle(value); } }
    private float _spreadRangeAngle = 40;

    public float Speed { get; set; } = 1000;

    public Lazy<Node> Entity;
    public Lazy<Node> EntityScene;

    private float _curCD;

    #endregion

    #region fields

    private DirectAndAngle[] _fireDirections = Array.Empty<DirectAndAngle>();

    #endregion

    #region ctors

    public MultiBulletMaker()
    {
        Entity = new Lazy<Node>(() => GetParent());
        EntityScene = new Lazy<Node>(() => Entity.Value.GetParent());
        MultiCount = 9;
        SpreadRangeAngle = 140;

    }

    #endregion

    #region godot
    // Called when the node enters the scene tree for the first time.
    public override void _Ready()
    {
    }

    // Called every frame. 'delta' is the elapsed time since the previous frame.
    public override void _Process(double delta)
    {
        _curCD += (float)delta;
        if (_curCD > CD)
        {
            _curCD = _curCD - CD;
            FireOnce();
        }

    }

    public override void _EnterTree()
    {
        base._EnterTree();

    }
    #endregion


    #region setters
    private void SetMultiCount(int value)
    {
        if (value == _multiCount) return;
        UpdateFireDirections(value, SpreadRangeAngle);
    }

    private void SetSpreadRangeAngle(float angleRange)
    {
        if (angleRange == _spreadRangeAngle) return;
        UpdateFireDirections(MultiCount, angleRange);
    }

    #endregion

    #region methods

    private void UpdateFireDirections(int multiCount, float angleRange)
    {
        _multiCount = multiCount;
        _spreadRangeAngle = angleRange;
        if (multiCount <= 0) throw new Exception("MultiBulletMaker.UpdateFireDirections: 子弹射出的方向需要大于零");

        var intervalAngle = 0f;

        if (multiCount == 0)
        {
            _fireDirections = new DirectAndAngle[] { new DirectAndAngle() { Angle = 0, Direct = Vector2.Up } };
            return;
        }
        else
        {

        }

        intervalAngle = angleRange / (multiCount - 1);

        // 奇和偶数的分叉是不一样的。
        var startVector = Vector2.Up.Rotated(-angleRange / 2 * MathF.PI / 180); // 从左边的第一个开始计算。

        var list = new List<DirectAndAngle>();

        for (int i = 0; i < multiCount; i++)
        {
            list.Add(new DirectAndAngle()
            {
                Direct = startVector.Rotated(intervalAngle * i * MathF.PI / 180),
                Angle = (-angleRange / 2 + intervalAngle * i) * MathF.PI / 180
            });
        }

        _fireDirections = list.ToArray();
    }

    #endregion

    private void FireOnce()
    {
        foreach (var fireDirection in _fireDirections)
        {
            var bullet = CreateBullet(Speed, fireDirection);
            if (bullet is null) continue;
            EntityScene.Value.AddChild(bullet);
        }
    }

    private Bullet CreateBullet(float speed, DirectAndAngle da)
    {
        if (Entity.Value is null) return null;
        var res = GD.Load<PackedScene>("res://Entities/Bullet/Bullet.tscn");

        var bullet = res.Instantiate<Bullet>();
        bullet.Speed = speed * da.Direct;

        bullet.Position = this.GlobalPosition;
        bullet.Rotation = da.Angle;
        return bullet;
    }
}
